home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-12-18 | 20.4 KB | 670 lines | [TEXT/ALFA] |
- ## -*-Tcl-*-
- # ###################################################################
- # Vince's Additions - an extension package for Alpha
- #
- # FILE: "TeXCompletions.tcl"
- # created: 26/2/96 {2:27:17 pm}
- # last update: 18/12/97 {8:28:19 am}
- # Author: Vince Darley
- # E-mail: <darley@fas.harvard.edu>
- # mail: Division of Applied Sciences, Harvard University
- # Oxford Street, Cambridge MA 02138, USA
- # www: <http://www.fas.harvard.edu/~darley/>
- #
- # Adds completion routines for TeX mode. This includes reference
- # (\label) completion, citation completion, environment completion,
- # environment item insertion.
- #
- # Also adds electric routines, and 'option-click-titlebar' code,
- # better cmd-dlb-click procedure, better marking for .sty files,
- # and much more...
- #
- # Cool new feature: the '{' key is bound to electric completion.
- # This means you can just type as normal in most circumstances,
- # and when you hit '{', if the previous text is capable of being
- # extended as a command (e.g. \begin, \frac, ...), then it is!
- #
- # modified by rev reason
- # -------- --- --- -----------
- # 18/12/97 VMD 1.1 added TeX::IncludeFile completions, better handling of '*'
- # ###################################################################
- ##
-
- # ◊◊◊◊ completions & expanders ◊◊◊◊ #
- ensureset completions(TeX) {beginContraction Env Cmd Electric Reference Cite Word}
- ensureset expanders(TeX) {ExCmd}
-
- # ◊◊◊◊ Preferences ◊◊◊◊ #
-
- # Add an item inside any environment
- # bound to shift-opt-i
- newPref binding TeXAddItem "/I<U<I" TeX "" 1
- # you can turn off the electric left brace with this:
- newPref flag elecLBrace 1 TeX
-
-
- newPref f showTitlesWithTeXCiteCompletion 1 TeX
- newPref v standardTeXLabelDelimiter ":" TeX TeX::labelDelimChanged
- # complete an environment even if we don't recognise it!
- newPref f acceptAnyTeXEnvironment 1 TeX
- # if we don't recognise the environment, create a body on the fly
- newPref f promptToCreateTeXEnvironment 1 TeX
- newPref f electricContractions 1 TeX
-
- # ◊◊◊◊ extra invoker key ◊◊◊◊ #
-
- proc TeX::electricLeft {} {
- global TeXmodeVars
- set p [getPos]
- if {$TeXmodeVars(electricContractions)} {
- catch {TeX::Completion::beginContraction}
- }
- if {[getPos] == $p} {
- catch {TeX::Completion::Electric}
- }
- if {[getPos] == $p} {typeText "\{"}
- }
-
- # ◊◊◊◊ Completions ◊◊◊◊ #
-
- ##
- # -------------------------------------------------------------------------
- #
- # "TeX::Completion::beginContraction" --
- #
- # The idea here is to see if you see a hint in the form of
- # "b'<some-word>", if so replace the "b'" with "\begin ".
- # -------------------------------------------------------------------------
- ##
- proc TeX::Completion::beginContraction {{dummy ""}} {
- set lastword [completion::lastTwoWords leadingHint]
- if {$leadingHint != "b'"} {return 0}
- set curPos [getPos]
- backwardWord
- set startEnvPos [getPos]
- set evironmentHint [getText $startEnvPos $curPos]
- backwardWord
- deleteText [getPos] $curPos
- insertText "\\begin"
- TeX::Completion::Electric "begin"
- typeText $lastword
- return 0
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "TeX::Completion::Env" --
- #
- # Complete the contents of a \begin...\end pair as appropriate. Uses the
- # TeXbodies array. You can either type '\begin<cmd-Tab>figure<cmd-Tab>'
- # (for example) or just '\begin{figure}<cmd-Tab>'.
- # -------------------------------------------------------------------------
- ##
- proc TeX::Completion::Env {dummy} {
- set cmd [completion::lastTwoWords begin]
- if { $begin != "\\begin\{" } { return 0 }
- if [regexp {^(.*)\}$} $cmd dmy cmd] {
- # hmm
- }
- set matches [completion::modeList $cmd TeXenvironments]
- if { $matches == 0 } {
- global TeXmodeVars TeXbodies
- if [info exists TeXbodies($cmd)] {
- set match $cmd
- } else {
- if {$TeXmodeVars(acceptAnyTeXEnvironment)} {
- if $TeXmodeVars(promptToCreateTeXEnvironment) {
- set y 40
- set yb 200
- set res [eval dialog -w 400 -h 340 \
- [dialog::title "New TeX environment" 400] \
- [dialog::button "OK" 310 yb] \
- [dialog::button "Cancel" 310 yb] \
- [dialog::text "Enter the template for the body of the environment" 10 y] \
- [dialog::text "Write '•prompt message•' for each template stop," 10 y] \
- [dialog::text "'\\r','\\\{','\\t',... for return, brace, tab etc." 10 y] \
- [dialog::edit "•body•" 10 y 35 6] \
- ]
- set match $cmd
- if {![lindex $res 1]} {
- eval set "TeXbodies($match)" [lindex $res 2]
- addUserLine "set TeXbodies($match) \"[quoteExpr3 $TeXbodies($match)]\""
- } else {
- # we cancelled, so move on
- completion::already error
- return 1
- }
- } else {
- message "Warning: I don't recognise that environment"
- set match $cmd
- }
- } else {
- return 0
- }
- }
- } else {
- set match [completion::Find $cmd $matches]
- }
- if [string length $match] {
- # we completed or cancelled, so move on
- completion::already error
- if { $match == 1 } {
- return 1
- } else {
- if {![ring::type]} {
- global TeXbodyOptions
- if [info exists TeXbodyOptions($match)] {
- endOfLine
- elec::Insertion $TeXbodyOptions($match)
- }
- ring::+
- set p [getPos]
- ring::+
- insertText $match
- goto $p
- return [elec::findCmd $match TeXbodies ""]
- }
- if {![ring::TMarkAt "environment name" [expr [getPos] - [string length $match]]]} {
- # we probably typed '\begin{name}' all in one go
- set i "••"
- if {[lookAt [expr [getPos]-1]] != "\}"} {
- append i "\}"
- }
- global TeXbodyOptions
- if [info exists TeXbodyOptions($match)] {
- append i $TeXbodyOptions($match)
- }
- append i "\r\t••\r\\end\{${match}\}\r••"
- elec::Insertion $i
- ring::+
- } else {
- global TeXbodyOptions
- if [info exists TeXbodyOptions($match)] {
- endOfLine
- elec::Insertion $TeXbodyOptions($match)
- }
- ring::+
- set p [getPos]
- # delete the stop of the body
- ring::deleteStopAndMove
- # delete the stop of the \end{•}
- ring::deleteStop
- # we need to fill in the '\end{}'
- insertText $match
- goto $p
- }
- set ret [elec::findCmd $match TeXbodies ""]
- # delete the stop of \begin{•}
- # we do this afterwards, otherwise we lose the nesting of
- # templates, which is bad.
- ring::-
- ring::deleteStopAndMove
- return $ret
- }
- } else {
- completion::already TeX::Completion::Env
- return 1
- }
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "TeX::Completion::Cmd" --
- #
- # Takes account of the backslash which commands in TeX use
- # -------------------------------------------------------------------------
- ##
- proc TeX::Completion::Cmd {dummy} {
- set cmd [completion::lastWord pos]
- if {[regexp {^\\([^\*]*)\*?$} $cmd "" cmd]} {
- return [completion::cmd [string range $cmd 1 end]]
- } else {
- return 0
- }
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "TeX::Completion::Electric" --
- #
- # An example of calling the completion::electric procedure.
- # In TeX mode, '{••}••' is a good default.
- # -------------------------------------------------------------------------
- ##
- proc TeX::Completion::Electric { {cmd ""} } {
- if ![string length $cmd] {
- if [containsSpace $cmd] { return 0 }
- set cmd [completion::lastWord]
- }
- if {[regexp {^\\([^\*]*)\*?$} $cmd "" cmd]} {
- # nothing
- } elseif {[regexp {\]\{?$} $cmd got]} {
- # we might have an optional [...] after the command we really want.
- # This should work but doesn't (Alpha bug)!
- #{matchIt "]" [pos::math [getPos] - [expr 1 + [string length $got]]]}
- if ![catch {search -s -f 0 -r 0 -m 0 "\[" [getPos]} where] {
- set p [getPos]
- goto [lindex $where 0]
- set cmd [completion::lastWord]
- goto $p
- regexp {^\\([^\*]*)\*?$} $cmd "" cmd
- }
- }
- return [completion::electric $cmd "\{••\}••"]
- }
-
-
- ##
- # -------------------------------------------------------------------------
- #
- # "TeX::Completion::Reference" --
- #
- # If we're in any kind of reference, search for appropriate labels to
- # get the information from and fill them in. 'TeXRefCompletion'
- # in "latexEngine.tcl" is obsolete.
- # -------------------------------------------------------------------------
- ##
- proc TeX::Completion::Reference { {dummy ""} } {
- global __wc__insPos completion_got completion_looking
- global _texrefprefixes
- # cursor changed place?
- set pos [getPos]
- if $pos==$__wc__insPos {
- completion::update TeX::Completion::Reference $completion_got $completion_looking
- message "press <Cmd Tab> for another label"
- return 1
- }
-
- global TeXmodeVars
-
- set lastword [completion::lastTwoWords prevword]
- set gotprefix ""
- set prevword [string trim [string range $prevword 1 end] "\{"]
- if {[set ref [lsearch -exact $TeXmodeVars(refCommands) $prevword]] != -1} {
- set gotprefix $lastword
- set lastword $prevword
- } else {
- # trim the backslash and opening brace:
- set lastword [string trim [string range $lastword 1 end] "\{"]
- # check if it's a \ref-like command:
- set ref [lsearch -exact $TeXmodeVars(refCommands) $lastword]
- }
-
- if { $ref != -1 } {
- # got a \ref-like command:
- set completion_got "\\[lindex $TeXmodeVars(refCommands) $ref]\{${gotprefix}"
- # make sure we have the brace:
- if { $gotprefix == "" && [lookAt [expr $pos -1]] != "\{" } {
- insertText "\{"
- }
- set completion_looking "label\{${gotprefix}"
- TeX::updateCompletion TeX::Completion::Reference $completion_got $completion_looking
- completion::already TeX::Completion::Reference
- return 1
- } else {
- completion::already TeX::Completion::Reference
- return 0
- }
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "TeX::Completion::Cite" --
- #
- # Checks for any \cite like command, and looks up the partial argument
- # in the known bibliographies, completing the entry as appropriate.
- # -------------------------------------------------------------------------
- ##
- proc TeX::Completion::Cite { {dummy ""} } {
- global __wc__insPos completion_got completion_looking TeXmodeVars
- # cursor changed place?
- if [getPos]==$__wc__insPos {
- set lastword [completion::lastWord]
- set completion_got [completion::modeList $lastword completion_got]
- } else {
- global TeXmodeVars
- set a [getText [lineStart [getPos]] [getPos]]
- # got a \cite-like command:
- if ![regexp "\\\\([join [string trim $TeXmodeVars(citeCommands)] |])\\\{(\[a-zA-Z0-9\]+,)*(\[a-zA-Z0-9\]+)$" $a d d d lastword] {
- return 0
- }
- set completion_got [bib_FindAllEntries $lastword $TeXmodeVars(showTitlesWithTeXCiteCompletion)]
- if {$completion_got == ""} {
- if {[askyesno "No matching citations found. Perhaps you should rebuild your bib data-base. Do you want to do this now?"] == "yes"} {
- if $TeXmodeVars(showTitlesWithTeXCiteCompletion) {
- bibMakeDatabase
- } else {
- bibMakeIndex
- }
- # try again
- return [TeX::Completion::Cite $dummy]
- }
- return 0
- } else {
- set completion_got " ${completion_got} "
- }
- }
- if $TeXmodeVars(showTitlesWithTeXCiteCompletion) {
- set query "Rebuild Bibliography Database"
- set rebuild bibMakeDatabase
- } else {
- set query "Rebuild Bibliography Index"
- set rebuild bibMakeIndex
- }
- set match [completion::Find $lastword $completion_got \
- $TeXmodeVars(showTitlesWithTeXCiteCompletion) 1 $query $rebuild]
- if {$match != ""} {
- if {[lookAt [getPos]] != "\}"} { insertText "\}" }
- }
- # we never bother with calling ourselves again, since we forced the above
- # 'completion::Find' call to complete.
- completion::already error
- return 1
- }
-
- proc TeX::Completion::Word {dummy} {
- # we only complete the word if it doesn't end in some command
- if { [lookAt [expr [getPos] -1]] != "\{" } {
- return [completion::word $dummy]
- }
- }
-
- # ◊◊◊◊ helpers ◊◊◊◊ #
-
- proc TeX::updateCompletion { proc {got ""} {looking ""} } {
- if [completion::general $got $looking] {
- completion::already $proc
- if {[lookAt [getPos]] != "\}"} {
- insertText "\}"
- }
- message "press <Cmd Tab> for another label"
- return 1
- } else {
- completion::already error
- # if {[lookAt [expr [getPos] - 1]] != "\}"} {
- # elec::Insertion "\}••"
- # }
- error ""
- return 0
- }
- }
-
- # ◊◊◊◊ experimental ◊◊◊◊ #
-
- ##
- # -------------------------------------------------------------------------
- #
- # "TeX::ForceCompletion::Cmd" --
- #
- # As far as I can see, this is not currently called anywhere. Perhaps it
- # is an abandoned experiment? -trf
- #
- # At one point is was useful, but currently not called as you say -vince
- # -------------------------------------------------------------------------
- ##
- proc TeX::Completion::ForceCmd {{dummy ""}} {
- global __g_cmd_start __g_last_match __g_last_match_pos __g_cmd_length TeXcmds
- set pos [getPos]
- set cmd [completion::lastWord cmd_start]
- # if there's any whitespace in the command then it's no good to us
- if [string match " \t" $cmd] { message "No command to complete"; return 0 }
- if { $cmd_start == $__g_cmd_start } {
- # it's an old match so we want the next
- if { [set found [lsearch [lrange $TeXcmds $__g_last_match_pos end] "\\${cmd}*" ]] == -1 } {
- message "No more commands"
- select $__g_cmd_start [expr $__g_cmd_start + [string length $__g_last_match]]]
- return 1
- } else {
- set oldLength [string length $__g_last_match]
- incr __g_last_match_pos $found
- set __g_last_match [lindex $TeXcmds $__g_last_match_pos]
- set completion [string range $__g_last_match $__g_cmd_length end]
- replaceText [expr $__g_cmd_start + $__g_cmd_length] \
- [expr $__g_cmd_start + $oldLength] \
- $completion
- }
- } else {
- # it's a new match
- if { [set __g_last_match_pos [lsearch $TeXcmds "\\${cmd}*" ]] == -1 } {
- message "No such command"; return 0
- } else {
- set __g_cmd_start $cmd_start
- set __g_last_match [lindex $TeXcmds $__g_last_match_pos]
- set __g_cmd_length [string length $cmd]
- incr __g_cmd_length -1
- set completion [string range $__g_last_match $__g_cmd_length end]
- insertText $completion
- }
- }
- return 1
- }
-
- # ◊◊◊◊ setup various arrays for electrics ◊◊◊◊ #
- uplevel \#0 [list source ${HOME}:Tcl:Completions:TeXcmds.tcl]
-
- proc TeX::labelDelimChanged {args} {
- uplevel \#0 {
- set _x $TeXmodeVars(standardTeXLabelDelimiter)
- set TeXelectrics(*section) "\{•section name•\}\n••"
- set TeXelectrics(frac) "\{•numerator•\}\{•denominator•\}••"
- set TeXelectrics(sum) "_\{•from•\}^\{•to•\}••"
- set TeXelectrics(emph) "◊1"
- set TeXelectrics(includegraphics) "◊\[TeX::IncludeFile\]"
- set TeXelectrics(begin) "\{•environment name•\}\n\t•body•\n\\end\{••\}\n••"
- set TeXelectrics(Sec*) "◊kill0Section~\\ref\{sec${_x}•label•\}••"
- set TeXelectrics(Table) "~\\ref\{tab${_x}•label•\}••"
- set TeXelectrics(App*) "◊kill0Appendix~\\ref\{sec${_x}•label•\}••"
- set TeXelectrics(Eq.) "~\\eqref\{eq${_x}•label•\}••"
- set TeXelectrics(Fig*) "◊kill0Figure~\\ref\{fig${_x}•label•\}••"
- set TeXelectrics(Cha*) "◊kill0Chapter~\\ref\{chap${_x}•label•\}••"
- #set TeXelectrics(subfigure) "\[•caption•\]\{\\label\{fig${_x}••\}\}\%\r\\includegraphics\[•width=,height=•\]\{•eps file•\}\}"
- set TeXbodies(equation) "•equation body•\n\\label\{eq${_x}•label•\}"
- set TeXbodies(description) "\\item\[•name•\] •description•\n\n\\item\[•name•\] •description•\n"
- set TeXbodies(enumerate) "\\item ••\n\n\\item ••\n"
- set TeXbodies(itemize) "\\item ••\n\n\\item ••\n"
- set TeXbodies(figure) "◊\[TeX::Figure\]"
- set TeXbodies(align) "•equation 1 l.h.s.• &•• \n\\label\{eq${_x}••\} \\\\\n•equation 2 l.h.s.• &•• \n\\label\{eq${_x}••\}"
- set TeXbodies(gather) "•• \n\\label\{eq${_x}••\} \\\\\n•• \n\\label\{eq${_x}••\}"
- set TeXbodies(split) "•• &•• \\\\\n•• &•• \\\\"
- set TeXbodies(cases) "•• & •• \\\\\n•• & ••"
- # currently these 'bodyOptions' cannot contain bullets
- set TeXbodyOptions(enumerate) "\[a|i\]"
- set TeXbodyOptions(figure) "\[tbp\]"
- set TeXbodyOptions(floatingfigure) "\{2in\}"
- set TeXEnvItems(enumerate) "\n\\item ••"
- set TeXEnvItems(itemize) "\n\\item ••"
- set TeXEnvItems(description) "\n\\item\[•name•\] •description•"
- set TeXEnvItems(align) "\\\\\n•next equation l.h.s.• &•• \n\\label\{eq${_x}••\} "
- set TeXEnvItems(gather) "\\\\\n•• \n\\label\{eq${_x}••\} "
- set TeXEnvItems(split) "•• &•• \\\\"
- set TeXEnvItems(cases) "•• &•• \\\\"
- set _texrefprefixes [list fig${_x} eq${_x} sec${_x} chap${_x} tab${_x} ]
- unset _x
- }
-
- }
-
- # call it now
- TeX::labelDelimChanged
-
- # ◊◊◊◊ label returners ◊◊◊◊ #
-
- proc TeX::labelDelim {} {
- global TeXmodeVars
- return $TeXmodeVars(standardTeXLabelDelimiter)
- }
- proc TeX::label {type} {
- global TeXmodeVars
- return "\\label\{${type}$TeXmodeVars(standardTeXLabelDelimiter)••\}"
- }
-
- # ◊◊◊◊ environment assistors ◊◊◊◊ #
-
- ##
- # -------------------------------------------------------------------------
- #
- # "TeXAddItem" --
- #
- # Scan the local environment and insert a new item into that environment,
- # of the appropriate type.
- #
- # Currently not too sophisticated.
- # -------------------------------------------------------------------------
- ##
- proc TeXAddItem {} {
- set env [lindex [split [eval getText [searchEnvironment]] "{}"] 1]
- global TeXEnvItems
- if ![catch {set item $TeXEnvItems($env)}] {
- elec::Insertion $item
- }
- }
-
- # ◊◊◊◊ Template embeddable proc's ◊◊◊◊ #
-
- proc TeX::IncludeFile {} {
- # could try to ensure this file's on the search path?
- if ![regexp {\{, } [lookAt [pos::math [getPos] - 1]]] {
- append res "\{"
- }
- append res [file tail [getfile "Name of file to include:"]]
- return $res
- }
-
- proc TeX::Figure {} {
- set fig_types [list "Normal" "Floating" \
- "2 side-by-side" "3 side-by-side" "4 side-by-side" \
- "2, one above the other" \
- "4 in a 2x2 block" \
- "6 with 3 across, 2 down" \
- "6 with 2 across, 3 down" \
- "other…" \
- ]
- set fig [listpick -p "Pick a figure type to insert:" $fig_types]
- if {$fig == ""} { return "" }
- set t ""
- switch $fig {
- "Normal" -
- "Floating" {
- append t "\\centerline\{\\includegraphics\[•shape,orientation•\]"
- append t "\{•graphics file•\}\}\r"
- append t "\\caption•\[short title for t.o.f.\]•\{•caption•\}\r"
- append t "\\protect[TeX::label fig]"
- if {$fig == "Floating"} {
- text::replace {\begin{figure}} {\begin{floatingfigure}} 0
- text::replace {\end{figure}} {\end{floatingfigure}} 1
- TeX::RequirePackage floatflt
- }
- }
- "2 side-by-side" {
- append t [TeX::_subFigure 2 1]
- }
- "3 side-by-side" {
- append t [TeX::_subFigure 3 1]
- }
- "4 side-by-side" {
- append t [TeX::_subFigure 4 1]
- }
- "2, one above the other" {
- append t [TeX::_subFigure 1 2]
- }
- "4 in a 2x2 block" {
- append t [TeX::_subFigure 2 2]
- }
- "6 with 3 across, 2 down" {
- append t [TeX::_subFigure 3 2]
- }
- "6 with 2 across, 3 down" {
- append t [TeX::_subFigure 2 3]
- }
- "other…" {
- set w [prompt "Number of subfigures, horizontally" "2"]
- set h [prompt "Number of subfigures, vertically" "2"]
- append t [TeX::_subFigure $w $h]
- }
-
- }
- return $t
- }
-
- # ◊◊◊◊ embeddable proc helpers ◊◊◊◊ #
-
- ##
- # -------------------------------------------------------------------------
- #
- # "TeX::_subFigure" --
- #
- # This is a helper, it is only called form the above proc.
- # -------------------------------------------------------------------------
- ##
- proc TeX::_subFigure {w h} {
- TeX::RequirePackage subfigure
- set t "\\centering\r"
- set wnum [lindex {x "" two three four five six seven} $w]
- for {set hh $h} {$hh >0} {incr hh -1} {
- for {set ww $w} {$ww >0} {incr ww -1} {
- append t "\\subfigure\[•subfig caption•\]\{[TeX::label fig]%\r"
- append t "\t\\includegraphics\[width=\\figs${wnum}\]"
- append t "\{•graphics file•\}\}"
- if {$ww != 1} {
- append t "\\goodgap${wnum}\r"
- } else {
- if {$hh != 1} {
- append t "\\\\\r"
- } else {
- append t "%\r"
- }
- }
- }
- }
- append t "\\caption•\[short caption for t.o.f.\]•\{•caption•\}\r"
- append t "[TeX::label fig]"
- }
-
- # ◊◊◊◊ Expansions ◊◊◊◊ #
- namespace eval TeX::Expansion {}
-
- proc TeX::Expansion::ExCmd { {cmd ""} {dictExt "acronyms"}} {
- if ![string length $cmd] {
- set cmd [completion::lastWord]
- # if there's any whitespace in the command then it's no good to us
- if [containsSpace $cmd] { return 0 }
- }
-
- set m [modeALike]
- set hint [string trim [join [split $cmd \\ ]]]
-
- if { [set matches [elec::acronymListExpansions $hint ${m}${dictExt}]] == 0 } {
- return 0
- } else {
- set result [elec::expandThis $cmd $matches]
- set match [lindex $result 0]
- catch {set keystroke [lindex $result 1]}
- if [string length $match] {
- # we completed or cancelled, so move on
- # WHY ISN'T THIS 'alreadyExpanding' ???????????? vmd
- completion::already error
- if { $match == 1 } {
- return 1
- } else {
- set curPos [getPos]
- set retVal [completion [modeALike] Electric "${match}"]
- # alertnote [expr ($retVal != 0) ]
- # alertnote [info exists keystroke]
- if {([getPos] == $curPos) && [info exists keystroke]} {
- insertText $keystroke
- }
- return $retVal
- }
- } else {
- elec::alreadyExpanding Cmd
- return 1
- }
- }
-
- }
-
-